import json
import time
from collections.abc import Callable
from pathlib import Path
from concurrent.futures import ThreadPoolExecutor, as_completed
from typing import Any
import pandas as pd
from ttp import ttp
from openpyxl import Workbook

# 线程池大小
Poll = 50
# 获取当前目录
BASE_DIR = Path(__file__).resolve().parent
# 获取当前日期
DATA = time.strftime('%Y-%m-%d', time.localtime())
# 获取当前日期时间
DATATIME = time.strftime('%Y-%m-%d %H.%M.%S', time.localtime())

EXCEL_FILE = f"{BASE_DIR.resolve().parent}/host.xlsx"

BASE_DIR.resolve().parent.joinpath(f"out/{DATA}").mkdir(exist_ok=True, parents=True)
# OUT_EXECL_FILE = f"{BASE_DIR.resolve().parent}/out/{DATA}/{DATATIME}-out.xlsx"
OUT_FILE = f"{BASE_DIR.resolve().parent}/out/{DATA}"


class Device:
    """
    设备模型
    """

    def __init__(
            self, hostname: str, host: str, username: str, password: str, device_type: str, port: int = 22,
            command_string: str = None, read_timeout: int = 15, is_parser: bool = False,
            templates: str = None
    ) -> None:
        self.hostname = hostname
        self.host = host
        self.username = username
        self.password = password
        self.port = port
        self.device_type = device_type
        self.port = port
        self.command_string = command_string
        self.read_time = read_timeout
        self.recv_data = None
        self.is_parser = is_parser
        self.templates = templates


class Templates:
    """
    设备模型
    """

    def __init__(self, ) -> None:
        pass


class Command:
    """
    命令模型
    """

    def __init__(self, command_string: str, strip_command: bool = False, strip_prompt: bool = False,
                 read_timeout: int = 30) -> None:
        self.command_string = command_string
        self.strip_command = strip_command
        self.strip_prompt = strip_prompt
        self.read_timeout = read_timeout


class Response:
    """
        Args:
        hostname (str): 设备名
        host (str): 设备IP
        status (str, optional): "success" | "info" |"error".
        data (any, optional): 获取的数据.
    """

    def __init__(self, hostname: str, host: str, data: Any):
        self._hostname = hostname
        self._host = host
        self._data = data

    @property
    def Success(self) -> str:
        """
        成功返回值
        :return:{'hostname': '111', 'host': '111', 'status': 'success', 'data': [{'11': '1x'}]}
        """
        # return dict(hostname=self._hostname, host=self._host, status="success", data=self._data)
        return f"{DATATIME}:{self._hostname}:{self._host}:success:{self._data}\n"

    @property
    def Error(self) -> str:
        """
         失败返回值
         :return:{'hostname': '111', 'host': '111', 'status': 'error', 'data': [{'11': '1x'}]}
         """
        # return dict(hostname=self._hostname, host=self._host, status="error", data=self._data)

        return f"{DATATIME}:{self._hostname}:{self._host}:error:{self._data}\n"

    @property
    def Info(self) -> str:
        """
         警告返回值
         :return:{'hostname': '111', 'host': '111', 'status': 'info', 'application': 'ssh', 'data': [{'11': '1x'}]}
         """
        # return dict(hostname=self._hostname, host=self._host, status="info", data=self._data)
        return f"{DATATIME}:{self._hostname}:{self._host}:info:{self._data}\n"


# def Handle_Parser(d: Device):
#     if not d.is_parser:
#         return d
#     d.recv_data = TTP_Parser(d)
#     return d
def TTP_Parser(d: Device) -> list:
    """解析ttp模版

    Args:
        d (Device): 解析的对象

    Returns:
        _type_: 解析后的数据
    """
    parser = ttp(data=d.recv_data, template=d.templates)
    parser.parse()
    # print("!!!!!",parser.result())
    return parser.result()[0][0]


def Handle_Parser(f: Callable):
    def wrapper(d: Device):
        if d.is_parser != "是":
            f(d)
        else:
            d.recv_data = TTP_Parser(d)
            f(d)

    return wrapper


@Handle_Parser
def Openpyxl_to_Excel(d: Device):
    wb = Workbook()
    # wb.create_sheet("out")
    ws = wb.active
    if isinstance(d.recv_data, str):
        title = ["主机名", "ip", "命令", "结果"]
        ws.append(title)
        ws.append([d.hostname, d.host, d.command_string, d.recv_data])
    elif isinstance(d.recv_data, list):
        data = d.recv_data
        title = [item for item in data[0]]
        # print(title)
        ws.append(title)
        for rows in data:
            column_number = 1
            for cols in title:
                ws.cell(row=data.index(rows) + 2, column=column_number).value = rows[cols]
                column_number += 1

    wb.save(f"{OUT_FILE}/{d.hostname} {d.host} {DATATIME}.xlsx")


@Handle_Parser
def Save_to_Txt(d: Device):
    with open(f"{OUT_FILE}/{d.hostname} {d.host} {DATATIME}.txt", encoding="utf-8", mode="w") as f:
        if isinstance(d.recv_data, str):
            f.write(d.recv_data)
        else:
            f.write(json.dumps(d.recv_data))


def Pandas_to_Dict(file: str, sheet_name: str = "host") -> list:
    df = pd.read_excel(file, sheet_name=sheet_name)
    data = df.to_dict(orient="records")
    return data


def Handel_Dict_Data(data: dict) -> list:
    """处理获取到oid数据

    Args:
        data (dict): 原始数据
        格式：
        {
            "xx":[],
            "yy":[],
            ....
        }
        规范，每个数组的值长度一致
    Returns:
        返回值: json类型的数据
        [{"xx":"x1","yy":"y1",...}]
    """
    df = pd.DataFrame(data=data)
    return df.to_dict(orient="records")


def Start_Thread(func: Callable, data: list) -> list:
    """
    开启线程池函数
    :param func:需要多线程的函数
    :param data:传递的参数
    :return:
    """
    with ThreadPoolExecutor(max_workers=Poll) as p:
        res = as_completed([p.submit(func, item) for item in data])
        response_data = [i.result() for i in res]
        return response_data


# def TTP_Parser(data: str, template: str) -> list:
#     """解析ttp模版
#
#     Args:
#         data (str): 解析的字符串
#         template (str): ttp模版
#
#     Returns:
#         _type_: 解析后的数据
#     """
#     parser = ttp(data=data, template=template)
#     parser.parse()
#     # print("!!!!!",parser.result())
#     return parser.result()[0][0]


def Log_File(message: str):
    with open(f"{BASE_DIR}/log.log", encoding="utf-8", mode="a+") as f:
        f.write(message)


def Response_Data(d: Device) -> dict:
    return dict(hostname=d.hostname, host=d.host, command_string=d.command_string, data=d.recv_data)


if __name__ == '__main__':
    # print(BASE_DIR)
    # print(Pandas_to_Dict(EXCEL_FILE, "host"))
    print(OUT_FILE)
    # Save_to_Text("!!!!!!")
    pass
